package com.ruoyi.web.service.impl;

import com.alibaba.fastjson2.JSON;
import com.ijpay.core.enums.SignType;
import com.ijpay.core.kit.WxPayKit;
import com.ijpay.wxpay.WxPayApi;
import com.ijpay.wxpay.model.UnifiedOrderModel;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.web.entity.pay.*;
import com.ruoyi.web.entity.pay.response.CreatePayResponse;
import com.ruoyi.web.entity.pay.response.WechatDataBean;
import com.ruoyi.web.service.WeChatPayService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Map;

/**
 * 用户 业务层处理
 * 
 * @author ruoyi
 */
@Service
public class WeChatPayServiceImpl implements WeChatPayService
{
    protected final Logger logger = LoggerFactory.getLogger(this.getClass());
    @Autowired
    private WeChatConfigBean weChatConfigBean;

    public WechatDataBean getTypeConfig(Integer tradeType){
        return weChatConfigBean.getTypeConfig(tradeType);
    }

    /**
     * 公共方法创建微信支付返回对象
     * @param orderId 订单号
     * @param realIp 下单ip
     * @param descTxt 描述文案
     * @param totalFee 充值金额
     * @return demo https://javen205.gitee.io/ijpay/guide/wxpay/#%E6%89%A9%E5%B1%95-model
     */
    @Override
    public CreatePayResponse getWxPayCommonResponse(Integer tradeType, String orderId, String realIp, String descTxt, Integer totalFee, String uuid) {

        // step1: 获取对应的配置项
        WechatDataBean wechatConfigBean = getTypeConfig(tradeType);

        logger.info("wechat对象: " + wechatConfigBean);

        // step2: 统一下单构建请求参数, 需注意观察每种类型的不一样
        String xmlResult = getWechatXmlResult(wechatConfigBean, descTxt, orderId, totalFee, realIp, uuid);

        logger.info("wechat返回结果: " + xmlResult);
        // 将请求返回的 xml 数据转为 Map，方便后面逻辑获取数据
        Map<String, String> result = WxPayKit.xmlToMap(xmlResult);

        // step3: 判断返回的结果

        String returnCode = result.get("return_code");
        String returnMsg = result.get("err_code_des");
        if (!WxPayKit.codeIsOk(returnCode)) {
            throw new ServiceException(returnMsg);
        }
        String resultCode = result.get("result_code");
        if (!WxPayKit.codeIsOk(resultCode)) {
            throw new ServiceException(returnMsg);
        }

        // step4: 以下字段在 return_code 和 result_code 都为 SUCCESS 的时候有返回
        String prepayId = result.get("prepay_id");

        // step5: 二次签名，构建公众号唤起支付的参数,这里的签名方式要与上面统一下单请求签名方式保持一致
        CreatePayResponse payResponse = new CreatePayResponse();
        if(tradeType == 3){
            // h5支付的比较特殊
//            packageParams.put("webUrl", result.get("mweb_url"));
//            packageParams.put("prepayid", prepayId);

            payResponse.setPrepayId(prepayId);
            payResponse.setWebUrl(result.get("mweb_url"));
        }else{
            // 根据不同类型返回数据
            payResponse = getWechatPackageParams(wechatConfigBean, prepayId);
        }

        return payResponse;
    }

    /**
     * 获取不同类型的xml请求参数
     */
    public String getWechatXmlResult(WechatDataBean wechatConfigBean, String descTxt , String orderId, Integer totalFee, String ip, String openId){

        /**
         * 小程序&&公众号 => openId
         * h5=>scene_info
         * app=>默认的即可
         */
        // step1: 获取对应的配置项
        Integer beanId = wechatConfigBean.getId();
        String appId = wechatConfigBean.getAppId();
        String type = wechatConfigBean.getType();
        String mchId = wechatConfigBean.getMchId();
        String mchKey = wechatConfigBean.getMchKey();
        String notifyUrl1 = wechatConfigBean.getNotifyUrl();
        String remark = wechatConfigBean.getRemark();
        String sceneInfoString = "";
        String body = descTxt + remark;
        if(beanId == 3){
            H5SceneInfo sceneInfo = new H5SceneInfo();

            H5SceneInfo.H5 h5_info = new H5SceneInfo.H5();
            h5_info.setType("Wap");
            // TODO 此域名必须在商户平台--"产品中心"--"开发配置"中添加
            h5_info.setWap_url("https://gitee.com/javen205/IJPay");
            h5_info.setWap_name("IJPay VIP 充值");
            sceneInfo.setH5Info(h5_info);
            sceneInfoString = JSON.toJSONString(sceneInfo);
        }

        Map<String, String> params = UnifiedOrderModel
                .builder()
                .appid(appId)
                .mch_id(mchId)
                .nonce_str(WxPayKit.generateStr())
                .body(body)
                .out_trade_no(orderId)
                .total_fee(String.valueOf(totalFee))
                .spbill_create_ip(ip)
                .notify_url(notifyUrl1)
                .trade_type(type)
                .scene_info(sceneInfoString)
                .openid(openId)
                .build()
                .createSign(mchKey, SignType.HMACSHA256)
            ;

        return WxPayApi.pushOrder(false, params);
    }

    /**
     * 获取不同类型的实际请求返回结果
     */
    public CreatePayResponse getWechatPackageParams(WechatDataBean wechatConfigBean, String prepayId){

        // step1: 获取对应的配置项
        Integer beanId = wechatConfigBean.getId();
        String appId = wechatConfigBean.getAppId();
        String mchId = wechatConfigBean.getMchId();
        String mchKey = wechatConfigBean.getMchKey();

        Map<String, String> packageParams = null;
        CreatePayResponse payResponse = new CreatePayResponse();

        if(beanId == 1){
            packageParams = WxPayKit.miniAppPrepayIdCreateSign(
                    appId, prepayId,
                    mchKey, SignType.MD5
            );
        } else if (beanId == 2) {
            packageParams = WxPayKit.prepayIdCreateSign(
                    prepayId, appId,
                    mchKey, SignType.MD5
            );

            payResponse.setTimestamp(packageParams.get("timeStamp"));
            payResponse.setSignType(packageParams.get("signType"));
            payResponse.setPackageS(packageParams.get("package"));
            payResponse.setPaySign(packageParams.get("paySign"));
            payResponse.setNonceStr(packageParams.get("nonceStr"));
            payResponse.setAppId(packageParams.get("appId"));
        } else if (beanId == 4) {
            packageParams = WxPayKit.appPrepayIdCreateSign(
                    appId, mchId,
                    prepayId, mchKey, SignType.MD5
            );
            payResponse.setPackageS(packageParams.get("package"));
            payResponse.setAppId(packageParams.get("appid"));
            payResponse.setSign(packageParams.get("sign"));
            payResponse.setPartnerId(packageParams.get("partnerid"));
            payResponse.setPartnerId(packageParams.get("prepayid"));
            payResponse.setNonceStr(packageParams.get("noncestr"));
            payResponse.setTimestamp(packageParams.get("timestamp"));
        }

        return payResponse;
    }



}
